package cn.piggy.gateway.core.config;

import cn.piggy.gateway.core.http.HttpStatement;
import cn.piggy.gateway.core.proxy.MyGenericReference;
import cn.piggy.gateway.core.proxy.cglib.MapperProxyFactoryManager;
import cn.piggy.gateway.core.proxy.jdk.ObjectProxyFactoryManager;
import cn.piggy.gateway.core.session.GatewaySession;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;


public class ConfigHelper {

    private String hostName = "127.0.0.1";
    private int port = 7397;
    private int bossNThreads = 1;
    private int workNThreads = 16;
    private String agentType = "jdk";
    public ConfigHelper() {}
    public String getAgentType() {
        return agentType;
    }
    public void setAgentType(String agentType) {
        this.agentType = agentType;
    }
    public String getHostName() {
        return hostName;
    }
    public void setHostName(String hostName) {
        this.hostName = hostName;
    }
    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        this.port = port;
    }
    public int getBossNThreads() {
        return bossNThreads;
    }
    public void setBossNThreads(int bossNThreads) {
        this.bossNThreads = bossNThreads;
    }
    public int getWorkNThreads() {
        return workNThreads;
    }
    public void setWorkNThreads(int workNThreads) {
        this.workNThreads = workNThreads;
    }

    private final Map<String, LinkedList<String>> servers = new HashMap<>();

    public Map<String, LinkedList<String>> getServers() {
        return servers;
    }

    public synchronized void registryAddr(String applicationName, String address){
        LinkedList<String> strings = servers.get(applicationName);
        if(strings==null){
            LinkedList<String> list = new LinkedList<>();
            list.add(address);
            servers.put(applicationName,list);
        }else{
            strings.add(address);
        }
    }

    public synchronized void deleteAddr(String applicationName, String address){
        LinkedList<String> strings = servers.get(applicationName);
        if(strings!=null){
            strings.remove(address);
        }
    }

    // RPC 应用服务配置项 api-application-test
    private final Map<String, ApplicationConfig> applicationConfigMap = new HashMap<>();
    // RPC 注册中心配置项 zookeeper://127.0.0.1:2181
    private final Map<String, RegistryConfig> registryConfigMap = new HashMap<>();
    // RPC 泛化服务配置项
    private final Map<String, ReferenceConfig<GenericService>> referenceConfigMap = new HashMap<>();


    /**
     * @param applicationName 系统名称
     * @param systemAddress zookeeper地址
     * @param interfaceName 接口名称
     * @param version 接口版本
     */
    public synchronized void registryConfig(String systemAddress, String applicationName, String interfaceName, String version) {
        if (applicationConfigMap.get(applicationName) == null) {
            ApplicationConfig application = new ApplicationConfig();
            application.setName(applicationName);
            application.setQosEnable(false);
            applicationConfigMap.put(applicationName, application);
        }

        if (registryConfigMap.get(applicationName) == null) {
            RegistryConfig registry = new RegistryConfig();
            registry.setAddress(systemAddress);
            registry.setRegister(true);
            registryConfigMap.put(applicationName, registry);
        }

        if (referenceConfigMap.get(applicationName+"##"+interfaceName) == null) {
            ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
            reference.setInterface(interfaceName);
            reference.setVersion(version);
            reference.setGeneric("true");
            referenceConfigMap.put(applicationName+"##"+interfaceName, reference);
        }
    }

    public synchronized void deleteReferenceConfig(String applicationName, String interfaceName) {
        referenceConfigMap.remove(applicationName+"##"+interfaceName);
    }
    public synchronized void deleteRegistryAndApplicationConfig(String applicationName) {
        registryConfigMap.remove(applicationName);
        applicationConfigMap.remove(applicationName);
    }
    public ApplicationConfig getApplicationConfig(String applicationName) {
        return applicationConfigMap.get(applicationName);
    }
    public RegistryConfig getRegistryConfig(String applicationName) {
        return registryConfigMap.get(applicationName);
    }
    public ReferenceConfig<GenericService> getReferenceConfig(String interfaceName) {
        return referenceConfigMap.get(interfaceName);
    }









    // key -> uri
    private final Map<String, HttpStatement> httpStatementMap = new HashMap<>();
    private final MapperProxyFactoryManager mapperManager = new MapperProxyFactoryManager();
    private final ObjectProxyFactoryManager objectManager = new ObjectProxyFactoryManager();

    public void addHttpStatement(String uri,HttpStatement httpStatement){
        httpStatementMap.put(uri, httpStatement);
    }
    public void deleteHttpStatement(String uri){
        httpStatementMap.remove(uri);
    }
    public synchronized void addMapperCjLib(HttpStatement httpStatement) {
        String uri = httpStatement.getUri();
        if (mapperManager.isExist(uri)) {
            return;
        }
        mapperManager.produceFactory(uri);
        addHttpStatement(uri, httpStatement);
    }
    public synchronized void deleteMapperCjLib(String uri) {
        mapperManager.destructionFactory(uri);
        deleteHttpStatement(uri);
    }
    public MyGenericReference getGenericReferenceCjLib(String uri, GatewaySession gatewaySession) {
        return mapperManager.getProxyObject(uri, gatewaySession);
    }


    public synchronized void addMapperJdk(HttpStatement httpStatement) {
        String uri = httpStatement.getUri();
        if (objectManager.isExist(uri)) {
            return;
        }
        objectManager.produceFactory(uri);
        addHttpStatement(uri, httpStatement);
    }

    public synchronized void deleteMapperJdk(String uri) {
        objectManager.destructionFactory(uri);
        deleteHttpStatement(uri);
    }

    public MyGenericReference getGenericReferenceJdk(String uri, GatewaySession gatewaySession) {
        return objectManager.getProxyObject(uri, gatewaySession);
    }

    public HttpStatement getHttpStatement(String uri) {
        return httpStatementMap.get(uri);
    }


}
